<script lang="ts" setup>
import { onMounted, reactive, getCurrentInstance, ref, onUnmounted, computed, watch } from 'vue'
import { useElementSize } from '@vueuse/core'
import { sendServiceData } from '../../common/service'
import { callLater, getTreeItem, travelTree } from '../../common/utils/normalUtils'
import { LIST_ALL_VALUE } from '../../common/manager/appConstManager'
import { queryOrgTreeApi } from '../../common/service/api/deptApi'

const emit = defineEmits(['update:modelValue', 'change', 'init'])
const props = defineProps({
  modelValue: {
    type: [String, Number],
    default: ''
  },
  hasOrg: {
    type: Boolean,
    default: true
  },
  eventData: {
    type: Boolean,
    default: true
  },
  openGroup: {
    type: Boolean,
    default: true
  },
  openLevel: {
    type: Number,
    default: 1
  },
  activeRoot: {
    type: Boolean,
    default: true
  },
  placeholder: {
    type: String,
    default: '请输入部门名称'
  },
  showRoot: {
    type: Boolean,
    default: false
  }
})

const state:any = reactive({
  init: false,
  isLoading: false,
  treeData: [],
  currentValue: props.modelValue,
  openItems: []
})

const treeRef:any = ref(null)
const treeBoxRef = ref(null)
const treeOptions = {
  value: 'id',
  label: 'label',
  children: 'children'
}

// 扁平化树结构
let treeMap:any = {}

const parentSize = useElementSize(treeBoxRef)
const containerHeight = computed(() => {
  return isNaN(parentSize.height.value) ? 200 : parentSize.height.value
})

/**
 *
 * @param val
 */
const initModelValue = (val:any) => {
  state.currentValue = val
}

/**
 *
 * @param data
 */
const changeHandler = (data: any, ev = true) => {
  state.currentValue = data.id
  emit('update:modelValue', state.currentValue)
  if (ev)emit('change', props.eventData ? treeMap[state.currentValue] : state.currentValue)
}

/**
 * 查询部门列表
 */
const queryRootList = async () => {
  treeMap = {}
  const openItems:any = []
  const result = await sendServiceData(queryOrgTreeApi, null, state)
  let list = result || []
  travelTree(list, (item:any, pItem:any, level:number) => {
    item.name = item.label
    item.type = 'group'
    treeMap[item.id] = item
  })
  if (props.showRoot) list = [{ name: '组织部门', id: LIST_ALL_VALUE, type: 'root', children: list }]
  if (list.length > 0)openItems.push(list[0].id)
  state.openItems = openItems
  state.treeData = list

  // 默认选中第一个 效率又低一层 列表接口支持默认查询所有两个异步效率会高点
  defaultActive(false)
  state.init = true
  emit('init', state.treeData)
}

/**
 *
 */
const defaultActive = (open = true) => {
  if (!props.activeRoot || state.treeData.length === 0) return
  callLater(() => {
    state.currentValue = props.modelValue || state.treeData[0].id
    defaultActiveItem(state.currentValue, open)
  })
}

/**
 * 节点过滤
 * @param query
 * @param node
 */
const filterMethod = (query: string, node: any) => {
  return node.name && node.name.indexOf(query) > -1
}

/**
 * 过滤
 * @param val
 */
const filter = (val:string) => {
  (treeRef.value as any).filter(val)
}

/**
 *
 * @param val
 * @param open
 */
const defaultActiveItem = (val:any, open = true) => {
  let defaultItem = null
  let openItems:any = []
  if (val) {
    travelTree(state.treeData, (item:any, pItem:any) => {
       if (!pItem)openItems = []
       else openItems.push(pItem.id)
       if (String(item.id) === String(val)) {
         defaultItem = item
         return -1
       }
    })
  }
  if (defaultItem && open) {
    state.openItems = openItems
    if (treeRef.value)treeRef.value.setExpandedKeys(openItems)
  }
  changeHandler(defaultItem || state.treeData[0])
}

watch(() => props.modelValue, (val:any) => {
  if (String(state.currentValue) !== String(val)) {
    state.currentValue = val
    if (val) defaultActiveItem(val)
  }
})

onMounted(() => {
  initModelValue(props.modelValue)
  queryRootList()
})

defineExpose({
  activeRootNode: (ev = true) => {
    if (state.treeData.length > 0) changeHandler(state.treeData[0], ev)
  }
})

</script>

<template>
  <div class="org-tree-box">
    <div class="search-title">
      <v-search-input v-model="state.inputValue"
                      :placeholder="placeholder"
                      @input="filter" />
    </div>
    <div ref="treeBoxRef" class="tree-content">
      <el-tree-v2 v-if="state.init"
                  ref="treeRef"
                  style="width:100%;"
                  highlight-current
                  auto-expand-parent
                  node-key="id"
                  :props="treeOptions"
                  :expand-on-click-node="false"
                  :data="state.treeData"
                  :current-node-key="state.currentValue"
                  :default-expanded-keys="state.openItems"
                  :height="containerHeight"
                  :filter-method="filterMethod"
                  @current-change="changeHandler">
        <template #default="{ node,data }">
          <v-icon :icon="data.type==='group'?'usergroup':(data.type==='root'?'group':'yonghu1')" class="tree-icon" />
          <span :class="['tree-lb',data.type==='root'?'tree-lb-root':'']">{{ data.name }}</span>
        </template>
      </el-tree-v2>
    </div>
  </div>
</template>

<style scoped lang="scss">

.org-tree-box{
  @include ver-group();
  flex:none;
  width:100%;
  height:100%;
  overflow: hidden;
  box-sizing: border-box;
  padding: 10px;

  .search-title{
    @include hor-group();
    flex:none;
    width:100%;
    height:var(--w-title-height);
  }

  .tree-content{
    flex:auto;
    width:100%;
    height:100%;
    overflow: hidden;
  }

}

  .tree-icon{
    font-size: 16px;
  }
  .tree-lb{
    padding-left:8px;
    box-sizing: border-box;
    word-break: keep-all;
    white-space: nowrap;
    font-size: 13px;
  }
  .tree-lb-root{
    font-weight: bold;
  }
</style>
